#include "nuc970.h"
#include "nuc970_i2c.h"
#include "nuc970_lcd.h"

void MFP_GPIOInit()
{
    outpw(REG_SYS_APBIPRST0, inpw(REG_SYS_APBIPRST0) | SYS_IPRST_GPIO);
    outpw(REG_SYS_APBIPRST0, inpw(REG_SYS_APBIPRST0) & (~SYS_IPRST_GPIO));
    outpw(REG_CLK_PCLKEN0, inpw(REG_CLK_PCLKEN0) | SYS_CLKEN_GPIO); //Enable GPIO engin clock.
}

void MFP_I2CInit(I2C_TypeDef *i2c)
{
    if (i2c == I2C0) {
        outpw(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | SYS_IPRST_I2C0);
        outpw(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & (~SYS_IPRST_I2C0));

        /* Configure multi function pins to I2C0 */
        outpw(REG_SYS_GPG_MFPL, (inpw(REG_SYS_GPG_MFPL) & ~0xFF) | 0x88);

        /* I2C clock pin enable schmitt trigger */
        outpw(REG_GPIOG_ISEN, (inpw(REG_GPIOG_ISEN) | 0x3));

        outpw(REG_CLK_PCLKEN1, inpw(REG_CLK_PCLKEN1) | SYS_CLKEN_I2C0);
    } else if (i2c == I2C1) {
        outpw(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | SYS_IPRST_I2C1);
        outpw(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & (~SYS_IPRST_I2C1));

        /* Configure multi function pins to I2C1 */
        outpw(REG_SYS_GPG_MFPL, (inpw(REG_SYS_GPG_MFPL) & ~0xFF00) | 0x8800);
        /* I2C clock pin enable schmitt trigger */
        outpw(REG_GPIOG_ISEN, (inpw(REG_GPIOG_ISEN) | 0x300));

        // outpw(REG_SYS_GPH_MFPL, (inpw(REG_SYS_GPH_MFPL) & ~0xFF00) | 0x8800);
        // /* I2C clock pin enable schmitt trigger */
        // outpw(REG_GPIOH_ISEN, (inpw(REG_GPIOH_ISEN) | 0x300));

        // outpw(REG_SYS_GPI_MFPL, (inpw(REG_SYS_GPI_MFPL) & ~0xFF000) | 0x88000);
        // /* I2C clock pin enable schmitt trigger */
        // outpw(REG_GPIOI_ISEN, (inpw(REG_GPIOI_ISEN) | 0x3000));

        outpw(REG_CLK_PCLKEN1, inpw(REG_CLK_PCLKEN1) | SYS_CLKEN_I2C1);
    }
}
void MFP_I2CDeInit(I2C_TypeDef *i2c)
{
    if (i2c == I2C0) {
        outpw(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | SYS_IPRST_I2C0);
        outpw(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & (~SYS_IPRST_I2C0));
        
        outpw(REG_SYS_GPG_MFPL, (inpw(REG_SYS_GPG_MFPL) & ~0xFF));
        
        outpw(REG_CLK_PCLKEN1, inpw(REG_CLK_PCLKEN1) & (~SYS_CLKEN_I2C0));
    } else if (i2c == I2C1) {
        outpw(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | SYS_IPRST_I2C1);
        outpw(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & (~SYS_IPRST_I2C1));

        outpw(REG_SYS_GPG_MFPL, (inpw(REG_SYS_GPG_MFPL) & ~0xFF00));
        // outpw(REG_SYS_GPH_MFPL, (inpw(REG_SYS_GPH_MFPL) & ~0xFF00));
        // outpw(REG_SYS_GPI_MFPL, (inpw(REG_SYS_GPI_MFPL) & ~0xFF000));

        outpw(REG_CLK_PCLKEN1, inpw(REG_CLK_PCLKEN1) & (~SYS_CLKEN_I2C1));
    }
}

void MFP_LCMInit(void)
{
    outpw(REG_SYS_AHBIPRST, inpw(REG_SYS_AHBIPRST) | SYS_IPRST_LCD);
    outpw(REG_SYS_AHBIPRST, inpw(REG_SYS_AHBIPRST) & (~SYS_IPRST_LCD));

    // Configure multi-function pin for LCD interface
    //GPG6 (CLK), GPG7 (HSYNC)
    outpw(REG_SYS_GPG_MFPL, (inpw(REG_SYS_GPG_MFPL)& ~0xFF000000) | 0x22000000);
    //GPG8 (VSYNC), GPG9 (DEN)
    outpw(REG_SYS_GPG_MFPH, (inpw(REG_SYS_GPG_MFPH)& ~0xFF) | 0x22);
    
    //DATA pin
    //GPA0 ~ GPA7 (DATA0~7)
    outpw(REG_SYS_GPA_MFPL, 0x22222222);
    //GPA8 ~ GPA15 (DATA8~15)
    outpw(REG_SYS_GPA_MFPH, 0x22222222);

#if defined(__NUC972DF62Y)
    //GPD8~D15 (DATA16~23)
    outpw(REG_SYS_GPD_MFPH, 0x22222222);
#elif defined(NUC976DK61Y)
#endif
    // LCD clock is selected from UPLL and divide to 20MHz
    outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xFF1F) | 0xE18);

    // enable lcd engine clock
    outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | SYS_CLKEN_LCD);
}

void MFP_LCMDeInit()
{
    // disable lcd engine clock
    outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) & (~SYS_CLKEN_LCD));
}
